package com.lu.common.aspect;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.lu.common.annotation.SystemLog;
import com.lu.common.utils.JwtUtil;
import com.lu.sys.entity.Log;
import com.lu.sys.entity.User;
import com.lu.sys.mapper.UserMapper;
import com.lu.sys.service.ILogService;
import com.lu.sys.service.IUserService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.time.LocalDateTime;


/**
 *  日志AOP增强
 *     boge3306[V]
 */
@Component
@Aspect
@EnableAspectJAutoProxy
public class LogAspect {

    @Autowired
    private JwtUtil jwtUtil;

    @Autowired
    private IUserService userService;

    @Autowired
    ILogService logService;

    @Pointcut("@annotation(com.lu.common.annotation.SystemLog)")
    public void logPointcut(){

    }

    @Around("logPointcut()")//环绕通知
    public Object around(ProceedingJoinPoint point) throws Throwable{
        // 执行的开始时间
        long begin = System.currentTimeMillis();
        Object obj = point.proceed();
        // 获取到 目标方法执行的时长
        long time = System.currentTimeMillis() - begin;
        // 保存日志操作的信息
        saveSysLog(point,time);
        return obj;
    }

//    /**
//     * 保存日志相关的方法
//     *     操作的用户
//     *     具体的操作
//     *     操作的方法名称
//     *     参数列表
//     *     执行的时长
//     *     客户端的ip
//     *     记录创建的时间
//     * @param point
//     */
    private void saveSysLog(ProceedingJoinPoint point,long time) {
        Log sysLog = new Log();
        // TODO 当前登录的用户
        //1.获取token
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        String token=request.getHeader("X-Token");
        //判断token
        if(StringUtils.isNotBlank(token)){
            //解析token，这里没有写token解析的具体方法
            User loginUser = jwtUtil.parseToken(token,User.class);
//            User user = userMapper.selectOne(new QueryWrapper<User>().eq("username", loginUser.getUsername()));
            sysLog.setUsername(loginUser.getUsername());
            System.out.println(loginUser.getUsername());
        }
        // 获取当前调用的方法
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        // 需要获取 方法@SysLog 注解的 描述信息
        SystemLog systemLogAnno = method.getAnnotation(SystemLog.class);
        if(systemLogAnno != null){
            // 绑定 operation 的值
            sysLog.setOperation(systemLogAnno.value());
        }
        // 绑定方法的名称
        String className = point.getTarget().getClass().getName();
        String methodName = method.getName();
        sysLog.setMethod(className+"."+methodName+"()");//什么类下的什么方法

        // 获取方法的参数
        Object[] paramsArgs = point.getArgs();
        String params = JSON.toJSON(paramsArgs).toString();
        sysLog.setParams(params);

        // 方法调用的执行时长
        sysLog.setTime(time);
        // 然后记录的创建时间
        sysLog.setCreateDate(LocalDateTime.now());

        logService.save(sysLog);

    }


}
